#https://github.com/1061700625/OpenMV_Face_Recognition
#https://book.openmv.cc/image/face.html
#https://book.openmv.cc/example/07-Face-Detection/face-detection.html

import sensor, time, image, ustruct
import os, time
import pyb
from pyb import Pin

#pyb模块 https://book.openmv.cc/MCU/pyb.html
red   = pyb.LED(1)
green = pyb.LED(2)
blue  = pyb.LED(3)
infrared = pyb.LED(4)
usart1 = pyb.UART(1, 9600)
usart3 = pyb.UART(3, 9600)
#flag = 0

# 控制模式
REGISTER_MODE = 0

#传感器设置
sensor.reset()
sensor.set_contrast(1)
sensor.set_gainceiling(16)
sensor.set_framesize(sensor.HQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.skip_frames(10)


Path_Backup = {'path':'', 'id':0}
rootpath = "/singtown"
# 差异度阈值
DIST_THRESHOLD = 15000

def debug(strings):
    print(strings)
    usart1.write(str(strings)+"\r\n")

def find(face_cascade, img):
    # Find objects.
    # Note: Lower scale factor scales-down the image more and detects smaller objects.
    # Higher threshold results in a higher detection rate, with more false positives.
    objects = img.find_features(face_cascade, threshold=0.75, scale=1.35)
    #image.find_features(cascade, threshold=0.5, scale=1.5),thresholds越大，
    #匹配速度越快，错误率也会上升。scale可以缩放被匹配特征的大小。
    if objects:
        print(len(objects))
        width_old = 0
        height_old = 0
        index = 0
        for n, r in enumerate(objects, 0):  # 寻找最大的face
            if r[2] > width_old and r[3] > height_old:
                width_old = r[2]
                height_old = r[3]
                index = n
        print("index:", index)
        img.draw_rectangle(objects[index])
        d0 = img.find_lbp((0, 0, img.width(), img.height()))
        res = match(d0)
        if res != 0:
            debug(res)
            return 1


def match(d0):  # 人脸识别
    green.on()
    dir_lists = os.listdir(rootpath)  # 路径下文件夹
    dir_num = len(dir_lists)          # 文件夹数量
    debug("*" * 60)
    debug("Total %d Folders -> %s"%(dir_num, str(dir_lists)))

    for i in range(0, dir_num):
        item_lists = os.listdir(rootpath+'/'+dir_lists[i])  # 路径下文件
        item_num = len(item_lists)                          # 文件数量
        debug("The %d Folder[%s], Total %d Files -> %s" %(i+1, dir_lists[i], item_num, str(item_lists)))

        Path_Backup['path'] = rootpath+'/'+dir_lists[i]  # 马上记录当前路径
        Path_Backup['id'] = item_num                     # 马上记录当前文件数量

        for j in range(0, item_num):  # 文件依次对比
            debug(">> Current File: " + item_lists[j])
            try:
                img = image.Image("/singtown/%s/%s" % (dir_lists[i], item_lists[j]), copy_to_fb=True)
            except Exception as e:
                debug(e)
                break
            d1 = img.find_lbp((0, 0, img.width(), img.height()))  # 提取特征值
            dist = image.match_descriptor(d0, d1)                 # 计算差异度
            debug(">> Difference Degree: " + str(dist))
            if dist < DIST_THRESHOLD:
                debug(">> ** Find It! **")
                green.on()
                time.sleep(1000)
                green.off()
                return item_lists[j]
    usart3.write("0")
    green.off()
    return 0


def register(face_cascade, img):

    global REGISTER_MODE
    if find(face_cascade, img) == 1:
        debug(">> Existing without registration!")
        REGISTER_MODE = 0
        return 0
    red.on()
    sensor.skip_frames(time = 5000)
    dir_lists = os.listdir(rootpath)  # 路径下文件夹
    debug(dir_lists)
    dir_num = len(dir_lists)          # 文件夹数量
    debug(dir_num)
    new_dir = ("%s/%d") % (rootpath, int(dir_num)+1)
    os.mkdir(new_dir)                 # 创建文件夹
    cnt = 5  # 拍摄5次图片
    red.off()
    while cnt:
        blue.on()
        sensor.skip_frames(time = 3000) # Give the user time to get ready.等待3s，准备一下表情。
        debug(new_dir)
        img = sensor.snapshot().save("%s/%d.pgm" % (new_dir, cnt))
        blue.off()
        debug(cnt)
        cnt -= 1
    REGISTER_MODE = 0
    #flag = 0

def main():
    global REGISTER_MODE
    try:
        os.mkdir(rootpath)
    except:
        pass
    #设置pin7为输入引脚，下拉
    pin7 = Pin('P7', Pin.IN, Pin.PULL_DOWN)  # 1为注册模式，即拍照存入
    face_cascade = image.HaarCascade("frontalface", stages=25)
    #try:
        #face_cascade = image.HaarCascade("/haarcascade_frontalcatface.cascade", stages=25)  # "frontalface"
    #except:
        #face_cascade = image.HaarCascade("frontalface", stages=25)
    clock = time.clock()
    img = None

    while (True):
        clock.tick()
        img = sensor.snapshot()
        if pin7.value() == 1:
        #if flag == 1:
            REGISTER_MODE = 1
        if REGISTER_MODE == 1:
            debug("REGISTER_MODE\r\n")
            register(face_cascade, img)
        else:
            res = find(face_cascade, img)
            if res==0:
                usart3.write("1")
main()
